home *** CD-ROM | disk | FTP | other *** search
/ Amiga Magazin: Amiga-CD 1996 March / Amiga-CD 1996 #3.iso / demos / stormc-demo / examples / fplot / fclass.cc next >
C/C++ Source or Header  |  1996-01-19  |  6KB  |  330 lines

  1. /*
  2.   Funktionsplotter in Storm C
  3.  
  4.   Function-Modul
  5.  
  6. */
  7.  
  8. #include <stream.h>
  9. #include <stdio.h>
  10. #include <math.h>
  11. #include <stdlib.h>
  12. #include <ctype.h>
  13.  
  14. #include "fclass.h"
  15.  
  16. // Destruktoren:
  17.  
  18. Func::~Func() { }       // Default: garnix
  19.  
  20. UnOpN::~UnOpN()
  21.  { delete arg; }
  22.  
  23. BinOpN::~BinOpN()
  24.  { delete l;
  25.    delete r;
  26.  }
  27.  
  28. // Konstruktoren:
  29.  
  30. double Func::Dummy;
  31.  
  32. KonstN::KonstN (double c)
  33.  { Konst = c; }
  34.  
  35. UnOpN::UnOpN(UnOps op, Func *n):
  36.  oper(op), arg(n)
  37. { }
  38.  
  39. BinOpN::BinOpN(BinOps op, Func *ln, Func *rn):
  40.  oper(op), l(ln), r(rn)
  41. { }
  42.  
  43. // "Konstant"-Funktionen:
  44.  
  45. int Func::isconst (double &retval)
  46.   { return 0; }
  47.  
  48. int KonstN::isconst (double &retval)
  49.   { retval = Konst;
  50.     return 1;
  51.   }
  52.  
  53. // Ausgabe
  54.  
  55. #define EPANIC 26731
  56.  
  57. void KonstN::print(char*)
  58.  {
  59.    printf("%g", Konst);
  60.  }
  61.  
  62. void VarN::print(char*)
  63.  { printf("x"); }
  64.  
  65. void ErrorN::print(char*)
  66.  { printf("?"); }
  67.  
  68. void UnOpN::print(char* str)
  69.   { switch(oper)
  70.     { case Op_neg: printf("-"); break;
  71.       case Op_sqr: printf("sqr "); break;
  72.       case Op_sqrt: printf("sqrt "); break;
  73.       case Op_sin: printf("sin "); break;
  74.       case Op_cos: printf("cos "); break;
  75.       case Op_exp: printf("exp "); break;
  76.       case Op_ln:  printf("ln "); break;
  77.     }
  78.     arg->print(str);
  79.   }
  80.  
  81. void BinOpN::print(char* str)
  82.   { printf("(");
  83.     l->print(str);
  84.     switch (oper)
  85.     { case Op_add: printf("+"); break;
  86.       case Op_sub: printf("-"); break;
  87.       case Op_mult:printf("*"); break;
  88.       case Op_div: printf("/"); break;
  89.       case Op_pot: printf("^"); break;
  90.       default: exit(EPANIC);
  91.     }
  92.     r->print(str);
  93.     printf(")");
  94.   }
  95.  
  96. // Auswertung
  97.  
  98. inline double sqr(double x)
  99.   { return x*x; }
  100.  
  101. double intpotz(double base, int exp)
  102.   { if (exp)
  103.       { if (exp<0) return 1.0/intpotz(base,-exp)
  104.         else if (exp==1) return base;
  105.         else if (exp&1) return base*sqr(intpotz(base, exp/2));
  106.                         else return sqr(intpotz(base, exp/2));
  107.        }
  108.      else return 1;
  109.   }
  110.  
  111. double UnOpN::eval (double x)
  112.  {
  113.    double y = arg->eval(x);
  114.  
  115.    switch(oper)
  116.    { case Op_neg:  return -y;
  117.      case Op_sqr:  return y*y;
  118.      case Op_sqrt: return sqrt(y);
  119.      case Op_sin:  return sin(y);
  120.      case Op_cos:  return cos(y);
  121.      case Op_exp:  return exp(y);
  122.      case Op_ln:   return log(y);
  123.      default: exit(EPANIC);
  124.    }
  125. }
  126.  
  127. double BinOpN::eval (double x)
  128.  { double lv = l->eval(x), rv = r->eval(x);
  129.    switch(oper)
  130.    { case Op_add:  return lv+rv;
  131.      case Op_sub:  return lv-rv;
  132.      case Op_mult: return lv*rv;
  133.      case Op_div:  return lv/rv;
  134.      case Op_pot:  if (r->isconst() && floor(rv)==rv)
  135.                      return intpotz(lv, int(rv))
  136.                    else if (lv > 0) return exp(rv*log(lv));
  137.                                     return 0;
  138.      default: exit(EPANIC);
  139.    }
  140.  }
  141.  
  142.  
  143. // ******** Parsing ********
  144.  
  145. #define EULER 2.7182818284
  146. #define PI 3.141592653589
  147.  
  148. char *cp;       // Zeiger auf String
  149. char c;         // gescanntes Zeichen
  150. short ErrFlag;  // Fehler aufgetreten?
  151.  
  152.  
  153. char Get()
  154. { while ((c = *cp) == ' ')
  155.     cp++;
  156.   if(c) cp++;
  157.   return c;
  158. }
  159.  
  160. Func *Fehler()
  161.  { if (!ErrFlag)
  162.      { cout << "\nError.\n";
  163.        ErrFlag = 1;
  164.      }
  165.    return new ErrorN;
  166.  }
  167.  
  168. Func *Expression();
  169.  
  170. Func *Term();
  171.  
  172. Func *Potenz();
  173.  
  174. Func *Factor()
  175. { while (c=='+') Get();
  176.  
  177.   if (c=='x' || c=='X')
  178.     { Get();
  179.       return new VarN;
  180.     }
  181.   else if (c >= '0' && c <= '9')
  182.     {
  183.       int i = 0;
  184.       enum {max = 80};
  185.       char numstr[max+1];
  186.  
  187.       while (isdigit(c) && i<max)
  188.         { numstr[i++] = c; Get(); }
  189.  
  190.       if (c=='.')
  191.         { numstr[i++] = c; Get(); }
  192.       while (isdigit(c) && i<max)
  193.         { numstr[i++] = c; Get(); }
  194.  
  195.       if (tolower(c)=='e')
  196.         { numstr[i++] = c; Get();
  197.  
  198.           if (c=='+' || c=='-')
  199.             { numstr[i++] = c; Get(); }
  200.           else
  201.           if (!isdigit(c))
  202.             return Fehler();
  203.  
  204.           while (isdigit(c) && i<max)
  205.             { numstr[i++] = c; Get(); }
  206.  
  207.         }
  208.  
  209.       numstr[i]=0;
  210.       return new KonstN(atof(numstr));
  211.      }
  212.    else
  213.    if (c=='(')
  214.      { Get();
  215.        Func *np = Expression();
  216.        if (c==')')
  217.          Get();
  218.        else
  219.          delete Fehler();
  220.        return np;
  221.      }
  222.    else
  223.    if (c=='c')
  224.      { if (Get()=='o' && Get() == 's')
  225.          { Get(); return new UnOpN(Op_cos, Factor()); }
  226.        else
  227.          return Fehler();
  228.      }
  229.    else
  230.    if (c=='e')
  231.      { if (Get()!='x')
  232.          return new KonstN(EULER);
  233.        else if (Get() == 'p')
  234.          { Get(); return new UnOpN(Op_exp, Factor()); }
  235.        else
  236.          return Fehler();
  237.      }
  238.    else if (c=='l')
  239.      { if (Get()=='n')
  240.          return Get(), new UnOpN(Op_ln, Factor());
  241.        else
  242.          return Fehler();
  243.      }
  244.    else if (c=='p')
  245.      { if (Get()!='i')
  246.          return Fehler();
  247.        Get(); return new KonstN(PI);
  248.      }
  249.    else if (c=='s')
  250.      { Get();
  251.        if (c=='i')
  252.          { if (Get() != 'n') return Fehler();
  253.            Get();
  254.            return new UnOpN(Op_sin, Factor());
  255.          }
  256.        else if (c=='q')
  257.          { if (Get() != 'r') return Fehler();
  258.            if (Get()=='t')
  259.              { Get();
  260.                return new UnOpN(Op_sqrt, Factor());
  261.              }
  262.            else return new UnOpN(Op_sqr, Factor());
  263.          }
  264.        else
  265.          return Fehler();
  266.      }
  267.  
  268.    // Default-Ergebnis:
  269.    return Fehler();
  270. }
  271.  
  272. Func *Potenz()
  273. {
  274.   Func *n1 = Factor();
  275.  
  276.   while (c=='^')
  277.     { Get();
  278.       Func *n2 = Factor();
  279.       n1 = new BinOpN(Op_pot, n1, n2);
  280.     }
  281.   return n1;
  282. }
  283.  
  284. Func *Term()
  285. { Func *n1 = Potenz();
  286.  
  287.   while (c=='*' || c=='/')
  288.     { BinOps op = c=='*'? Op_mult : Op_div;
  289.       Get();
  290.       Func *n2 = Potenz();
  291.       n1 = new BinOpN(op, n1, n2);
  292.     }
  293.   return n1;
  294. }
  295.  
  296. Func *Expression()
  297. {
  298.   if (c=='-')
  299.    { Get();
  300.      Func *np = Term();
  301.        return new UnOpN(Op_neg,np);
  302.    }
  303.   else
  304.    { Func *n1 = Term();
  305.      while (c=='+' || c=='-')
  306.        { BinOps op = c=='+'? Op_add : Op_sub;
  307.          Get();
  308.          Func *n2 = Term();
  309.          n1 = new BinOpN(op, n1, n2);
  310.        }
  311.      return n1;
  312.    }
  313. }
  314.  
  315. Func *Parse(char *string)
  316. { cp = string;
  317.   ErrFlag = 0;
  318.  
  319.   Get();
  320.   Func *expr = Expression();
  321.   if (c) delete Fehler();
  322.  
  323.   if(ErrFlag)
  324.     { delete expr; return 0; }
  325.   else
  326.     return expr;
  327. }
  328.  
  329.  
  330.